﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace DataSyn.Forms
{
    public partial class FormMain : FormBase
    {
        DAL.Project project_edit = null;
        DAL.ConnectionSetting conn_edit = null;
        DAL.Table table_edit = null;
        public FormMain()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            LoadProject();
            foreach (var pro in MDL.CPublic.config.Project_All)
                if (ClassLibrary_Public.CConver.getBool(pro.IsRunning))
                    MDL.CPublic.syncManager.GetOrCreateProject(pro);
        }
        private void LoadProject()
        {
            projectBindingSource.Clear();
            var projects = MDL.CPublic.config.Project_All;
            if (projects != null && projects.Length > 0)
                projectBindingSource.DataSource = projects.Select(c=>new DAL.Project() { ProjectName=c.ProjectName, MasterConnName=c.MasterTableName, IsRunning=ClassLibrary_Public.CConver.getBool( c.IsRunning), SleepMsec=c.SleepMsec }).OrderBy(c=>c.ProjectName).ToList();
            else
                projectBindingSource.DataSource = new List<DAL.Project>() { };
        }
        private void LoadDataBase()
        {
            connectionSettingBindingSource.DataSource = new List<DAL.ConnectionSetting>();
            if (project_edit == null)
                return;
            var project = MDL.CPublic.config.GetProject(project_edit.ProjectName);
            if (project != null)
            {
                var conns = project.ConnCollection.Cast<MDL.ConfigSet.ConnElement>().ToArray();
                if (conns != null && conns.Length > 0)
                    connectionSettingBindingSource.DataSource = conns
                        .Select(c => new { connName = c.ConnName, IsRunning = c.IsUsed, conn = new CDataContext.ConnectionSetting.Conn() { Provider_Str = c.Provider, Connection = c.ConnectionString } })
                        .Select(c => new DAL.ConnectionSetting() { connectionName = c.connName, connectionString = c.conn.Connection, dataBase = c.conn.dataName, datasource = c.conn.dataSource, provider = c.conn.Provider_Str, isRunning = ClassLibrary_Public.CConver.getBool(c.IsRunning) })
                        .ToList();
                else
                    connectionSettingBindingSource.DataSource = new List<DAL.ConnectionSetting>();
                if (project.MasterConn != null)
                {
                    var masterconn = project.MasterConn;
                    var conn = new { connName = masterconn.ConnName, IsRunning = masterconn.IsUsed, conn = new CDataContext.ConnectionSetting.Conn() { Provider_Str = masterconn.Provider, Connection = masterconn.ConnectionString } };
                    connectionSettingBindingSource.Insert(0, new DAL.ConnectionSetting() { connectionName = conn.connName, connectionString = conn.conn.Connection, dataBase = conn.conn.dataName, datasource = conn.conn.dataSource, provider = conn.conn.Provider_Str, isRunning = ClassLibrary_Public.CConver.getBool(conn.IsRunning) });
                }
            }
            BuildMasterConnName();
        }
        private void BuildMasterConnName()
        {
            repositoryItemComboBox_MasterConnName.Items.Clear();
            var t1 = (connectionSettingBindingSource.DataSource as List<DAL.ConnectionSetting>).Where(c => !string.IsNullOrWhiteSpace(c.connectionName)).ToList();
            if (t1 != null && t1.Count > 0)
                repositoryItemComboBox_MasterConnName.Items.AddRange(t1.Select(c => c.connectionName).ToArray());
            ReadMasterConn();
        }
        private void barButtonItem_Project_Add_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            var project = projectBindingSource.AddNew() as DAL.Project;
        }

        private void gridView_Project_ValidatingEditor(object sender, DevExpress.XtraEditors.Controls.BaseContainerValidateEditorEventArgs e)
        {
            if (gridView_Project.FocusedColumn == colProjectName)
            {
                string value = string.Format("{0}", e.Value);
                if (string.IsNullOrWhiteSpace(value))
                {
                    MessageBox.Show("项目名称必填！");
                    e.Valid = false;
                    e.ErrorText = "项目名称必填!";
                }
                else
                {

                    MDL.CPublic.config.SetProject(
                            new MDL.ConfigSet.ProjectSection() { ProjectName = value, IsRunning = project_edit.IsRunning.ToString(), MasterTableName = project_edit.MasterConnName, SleepMsec = project_edit.SleepMsec },
                            project_edit.ProjectName
                        );
                }
            }
            else if (gridView_Project.FocusedColumn == colMasterConnName)
            {
                MDL.CPublic.config.SetProject(new MDL.ConfigSet.ProjectSection() { ProjectName = project_edit.ProjectName, MasterTableName = string.Format("{0}", e.Value), IsRunning = project_edit.IsRunning.ToString(), SleepMsec = project_edit.SleepMsec });
            }
            else if (gridView_Project.FocusedColumn == colSleepMsec)
            {
                MDL.CPublic.config.SetProject(
                         new MDL.ConfigSet.ProjectSection() { ProjectName = project_edit.ProjectName, IsRunning = project_edit.IsRunning.ToString(), MasterTableName = project_edit.MasterConnName, SleepMsec = ClassLibrary_Public.CConver.getInt(e.Value) },
                         project_edit.ProjectName
                     );
            }
        }
        private void gridView_Project_CellValueChanging(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e)
        {
            if (gridView_Project.FocusedColumn == colIsRunning)
            {
                MDL.CPublic.config.SetProject(new MDL.ConfigSet.ProjectSection() { ProjectName = project_edit.ProjectName, IsRunning = string.Format("{0}", e.Value), MasterTableName = project_edit.MasterConnName, SleepMsec = ClassLibrary_Public.CConver.getInt(project_edit.SleepMsec) });
            }
        }
        private void projectBindingSource_CurrentChanged(object sender, EventArgs e)
        {
            project_edit = projectBindingSource.Current as DAL.Project;
            LoadDataBase();
            ReadMasterConn();
        }

        private void barButtonItem_DataBase_Add_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            conn_edit = connectionSettingBindingSource.AddNew() as DAL.ConnectionSetting;
        }

        private void connectionSettingBindingSource_CurrentChanged(object sender, EventArgs e)
        {
            conn_edit = connectionSettingBindingSource.Current as DAL.ConnectionSetting;
        }

        private void gridView_DataBase_ValidatingEditor(object sender, DevExpress.XtraEditors.Controls.BaseContainerValidateEditorEventArgs e)
        {
            if (gridView_DataBase.FocusedColumn == colconnectionName)
            {
                string value = string.Format("{0}", e.Value);
                if (string.IsNullOrWhiteSpace(value))
                {
                    MessageBox.Show("连接名必填！");
                    e.Valid = false;
                    e.ErrorText = "连接名必填！";
                }
                else
                {
                    if (string.IsNullOrWhiteSpace(conn_edit.connectionName))
                    {
                        MDL.CPublic.config.GetProject(project_edit.ProjectName).ConnCollection.Set(new MDL.ConfigSet.ConnElement()
                        {
                            ConnectionString = string.Format("{0}", conn_edit.connectionString),
                            ConnName = string.Format("{0}", value),
                            IsUsed = conn_edit.isRunning.ToString(),
                            Provider = string.Format("{0}", conn_edit.provider)
                        });
                    }
                    else
                    {
                        var tem = MDL.CPublic.config.GetProject(project_edit.ProjectName).ConnCollection;
                        tem.Remove(conn_edit.connectionName);
                        tem.Set(new MDL.ConfigSet.ConnElement()
                        {
                            ConnectionString = string.Format("{0}", conn_edit.connectionString),
                            ConnName = string.Format("{0}", value),
                            IsUsed = conn_edit.isRunning.ToString(),
                            Provider = string.Format("{0}", conn_edit.provider)
                        });
                    }
                    
                    MDL.CPublic.config.Save();
                    ReadMasterConn();
                }
            }
        }
        private void gridView_DataBase_CellValueChanging(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e)
        {
            if (gridView_DataBase.FocusedColumn == colDataBaseIsRunning)
            {
                var project = MDL.CPublic.config.GetProject(project_edit.ProjectName);
                bool isRunning = ClassLibrary_Public.CConver.getBool(project.IsRunning);
                MDL.CPublic.syncManager.GetOrCreateProject(project, true).StopSync();
                if (!string.IsNullOrWhiteSpace(conn_edit.connectionName))
                {
                    var tem = MDL.CPublic.config.GetProject(project_edit.ProjectName).ConnCollection;
                    tem.Remove(conn_edit.connectionName);
                    tem.Set(new MDL.ConfigSet.ConnElement()
                    {
                        ConnectionString = string.Format("{0}", conn_edit.connectionString),
                        ConnName = string.Format("{0}", conn_edit.connectionName),
                        IsUsed = string.Format("{0}", e.Value),
                        Provider = string.Format("{0}", conn_edit.provider)
                    });
                }
                MDL.CPublic.config.Save();
                ReadMasterConn();
                if (isRunning)
                    MDL.CPublic.syncManager.GetOrCreateProject(project, true).StartSync();
            }
        }
        private void gridView_DataBase_ValidateRow(object sender, DevExpress.XtraGrid.Views.Base.ValidateRowEventArgs e)
        {
            
        }
        
        private void repositoryItemButtonEdit_DataBase_ButtonClick(object sender, DevExpress.XtraEditors.Controls.ButtonPressedEventArgs e)
        {
            if (string.IsNullOrWhiteSpace(conn_edit.provider))
                conn_edit.provider = ClassLibrary_Public.CEnum.getName(CDataContext.EProvider.None);
            using (CDataContext.ConnectionSetting.WinForm.Form_Setting form = new CDataContext.ConnectionSetting.WinForm.Form_Setting() { provider=ClassLibrary_Public.CEnum.getValue<CDataContext.EProvider>( conn_edit.provider), Connection=conn_edit.connectionString })
            {
                if (form.ShowDialog() == DialogResult.OK)
                {
                    CDataContext.ConnectionSetting.Conn conn = new CDataContext.ConnectionSetting.Conn() { Provider=form.provider,Connection=form.Connection };
                    conn_edit.provider = conn.Provider_Str;
                    conn_edit.connectionString = conn.Connection;
                    conn_edit.dataBase = conn.dataName;
                    conn_edit.datasource = conn.dataSource;
                    connectionSettingBindingSource.ResetCurrentItem();
                    if (!string.IsNullOrWhiteSpace(conn_edit.connectionName))
                    {
                        var proj=MDL.CPublic.config.GetProject(project_edit.ProjectName);
                        if (proj.MasterConn != null && proj.MasterConn.ConnName == conn_edit.connectionName)
                        {
                            proj.MasterConn.ConnectionString = conn_edit.connectionString;
                        }
                        else
                        {
                            var tem = MDL.CPublic.config.GetProject(project_edit.ProjectName).ConnCollection;
                            tem.Remove(conn_edit.connectionName);
                            tem.Set(new MDL.ConfigSet.ConnElement()
                            {
                                ConnectionString = string.Format("{0}", conn_edit.connectionString),
                                ConnName = string.Format("{0}", conn_edit.connectionName),
                                IsUsed = conn_edit.isRunning.ToString(),
                                Provider = string.Format("{0}", conn_edit.provider)
                            });
                        }
                    }
                    MDL.CPublic.config.Save();
                    ReadMasterConn();
                }
            }
        }

        private void connectionSettingBindingSource_CurrentItemChanged(object sender, EventArgs e)
        {
            BuildMasterConnName();
            ReadMasterConn();
        }
        private void ReadMasterConn()
        {
            List<DAL.Table> list_table = new List<DAL.Table>();
            try
            {
                var project = MDL.CPublic.config.GetProject(project_edit.ProjectName);
                if (project == null)
                    throw new Exception("未找到项目！");
                var mastConn = project.MasterConn;
                if (mastConn == null) throw new Exception("未找到主连接！");
                var conn = new CDataContext.ConnectionSetting.Conn() { Provider_Str = mastConn.Provider, Connection = mastConn.ConnectionString };
                using (CDataContext.DataContext dc = new CDataContext.DataContext(conn.Provider, conn.Connection))
                {
                    var tables = dc.getTables();
                    if (tables != null && tables.Length > 0)
                        list_table.AddRange(tables.Where(c=>c.schemaName!="sync").OrderBy(c=>c.tableName).Select(c => new DAL.Table() { MasterTableName = string.Format("{0}.{1}", c.schemaName, c.tableName) }));
                }
                #region 清除无效表名
                {
                    var tables = project.TableCollection.Select(c => c.TableName).ToArray();
                    foreach (string table in tables)
                        if (list_table.Count(c => c.MasterTableName == table) == 0)
                            project.TableCollection.Remove(table);
                }
                #endregion
                #region 得到要同步的表名
                {
                    foreach (var table in list_table)
                        if (project.TableCollection.Count(c => c.TableName == table.MasterTableName) > 0)
                            table.IsSync = true;
                }
                #endregion
                #region 得到当前连接的表名
                if (conn_edit != null)
                {
                    var clientConnElement = project.ConnCollection.FirstOrDefault(c => c.ConnName == conn_edit.connectionName);
                    if (clientConnElement != null)
                    {
                        #region 清除无用表名
                        var tables = clientConnElement.TableCollection.ToArray();
                        foreach (var table in tables)
                            if (list_table.Count(c => c.MasterTableName == table.TableName && c.IsSync) == 0)
                                clientConnElement.TableCollection.Remove(table.TableName);
                        #endregion
                        #region 添加要同步的表名
                        foreach (var table in list_table.Where(c => c.IsSync))
                        {
                            var tem = clientConnElement.TableCollection.FirstOrDefault(c => c.TableName == table.MasterTableName);
                            if (tem == null)
                                tem = new MDL.ConfigSet.TableElement() { TableName = table.MasterTableName, ClientTableName = table.ClientTableName };
                            if (string.IsNullOrWhiteSpace(table.ClientTableName))
                                table.ClientTableName = table.MasterTableName;
                            clientConnElement.TableCollection.Set(tem);
                        }
                        #endregion
                    }
                }
                MDL.CPublic.config.Save();
                #endregion
            }
            catch (Exception ex)
            {
                list_table.Clear();
            }

            tableBindingSource.DataSource = list_table;
            tableBindingSource.Sort = "MasterTableName";
        }

        private void gridView_Project_CellValueChanged(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e)
        {
            ReadMasterConn();
        }

        private void gridView_DataBase_CellValueChanged(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e)
        {
            ReadMasterConn();
        }

        private void tableBindingSource_CurrentChanged(object sender, EventArgs e)
        {
            table_edit = tableBindingSource.Current as DAL.Table;
        }

       
        private void tableBindingSource_CurrentItemChanged(object sender, EventArgs e)
        {
            
        }

        private void gridView_Table_CellValueChanged(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e)
        {
           
        }
        private void gridView_Table_CellValueChanging(object sender, DevExpress.XtraGrid.Views.Base.CellValueChangedEventArgs e)
        {
            if (table_edit == null || project_edit == null || conn_edit == null)
                return;
            var project = MDL.CPublic.config.GetProject(project_edit.ProjectName);
            if (project == null) return;
            if (e.Column == colIsSync)
            {
                if (ClassLibrary_Public.CConver.getBool(e.Value))
                {
                    project.TableCollection.Set(new MDL.ConfigSet.TableElement() { TableName = table_edit.MasterTableName });
                }
                else
                {
                    project.TableCollection.Remove(table_edit.MasterTableName);
                }
            }
            if (table_edit.IsSync)
            {
                foreach (var conn in project.ConnCollection)
                {
                    var table = conn.TableCollection.FirstOrDefault(c => c.TableName == table_edit.MasterTableName);
                    if (table == null)
                        table = new MDL.ConfigSet.TableElement() { TableName = table_edit.MasterTableName, ClientTableName = table_edit.ClientTableName };
                    if (string.IsNullOrWhiteSpace(table_edit.ClientTableName))
                        table.ClientTableName = table.TableName;
                    conn.TableCollection.Set(table);
                }
            }
            else
            {
                foreach (var conn in project.ConnCollection)
                {
                    if (conn.TableCollection.Count(c => c.TableName == table_edit.MasterTableName) > 0)
                        conn.TableCollection.Remove(table_edit.MasterTableName);
                }
            }
            MDL.CPublic.config.Save();
            if (ClassLibrary_Public.CConver.getBool(project.IsRunning))
            {
                var t1 = MDL.CPublic.syncManager.GetOrCreateProject(project);
                t1.StartSync();
            }
        }

        private void repositoryItemButtonEdit_MastConn_ButtonClick(object sender, DevExpress.XtraEditors.Controls.ButtonPressedEventArgs e)
        {
            var project = MDL.CPublic.config.GetProject(project_edit.ProjectName);
            if (project == null) return;
            switch (e.Button.Caption)
            {
                case "初始化":
                    {
                        MDL.CPublic.syncManager.GetOrCreateProject(project).CreateMaster();
                    }
                    break;
                case "取消":
                    {
                        MDL.CPublic.syncManager.GetOrCreateProject(project).CancelMaster();
                    }
                    break;
            }
        }

        private void repositoryItemButtonEdit_ConnOperator_ButtonClick(object sender, DevExpress.XtraEditors.Controls.ButtonPressedEventArgs e)
        {
            var project = MDL.CPublic.config.GetProject(project_edit.ProjectName);
            var ma=MDL.CPublic.syncManager.GetOrCreateProject(project);
            ma.StartSync();
        }

        private void timer_SyncStatu_Tick(object sender, EventArgs e)
        {
            if (project_edit == null) return;
            var project = MDL.CPublic.config.GetProject(project_edit.ProjectName);
            if (project == null || !ClassLibrary_Public.CConver.getBool(project.IsRunning))
                return;
            var pro = MDL.CPublic.syncManager.GetOrCreateProject(project).progress;
            barStaticItem_SyncConnName.Caption = string.Format("当前连接：{0}", pro.connName);
            barStaticItem_SyncTableName.Caption = string.Format("当前同步表：{0}", pro.tableName);
            barStaticItem_SyncProgress.Caption = string.Format("当前进度：{0:N0}/{1:N0}", pro.count, pro.count_All);
            if (ClassLibrary_Public.CConver.getInt(barEditItem_SyncProgress.EditValue) == 0)
                repositoryItemProgressBar_SyncProgress.Maximum = pro.count_All;
            barEditItem_SyncProgress.EditValue = pro.count;
            barStaticItem_SyncMsg.Caption = string.Format("{0}", pro.msg);
        }

        private void FormMain_FormClosing(object sender, FormClosingEventArgs e)
        {
            MDL.CPublic.syncManager.ClosedAll();
        }

        private void barButtonItem_DataBase_Remove_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (project_edit == null) return;
            var conn_edit = connectionSettingBindingSource.Current as DAL.ConnectionSetting;
            if (conn_edit == null) return;
            var project = MDL.CPublic.config.GetProject(project_edit.ProjectName);
            MDL.CPublic.syncManager.RemoveProject(project);
            project.ConnCollection.Remove(conn_edit.connectionName);
            MDL.CPublic.config.Save();
            gridView_DataBase.RefreshData();
        }

        private void barButtonItem_Project_Delete_ItemClick(object sender, DevExpress.XtraBars.ItemClickEventArgs e)
        {
            if (project_edit != null)
                MDL.CPublic.config.RemoveProject(project_edit.ProjectName);
            gridView_Project.RefreshData();
        }

       
    }
}
